package com.example.demo.security.provider;

import com.example.demo.security.service.CustomUserDetailsService;
import com.example.demo.security.CustomWebAuthenticationDetails;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private CustomUserDetailsService customUserDetailsService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    // 获取用户输入的用户名和密码
    String inputName = authentication.getName();
    String inputPassword = authentication.getCredentials().toString();

    CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication
        .getDetails();

    String verifyCode = details.getVerifyCode();
    if (!validateVerify(verifyCode)) {
      throw new DisabledException("验证码输入错误");
    }

    // userDetails为数据库中查询到的用户信息
    UserDetails userDetails = customUserDetailsService.loadUserByUsername(inputName);

    // 如果是自定义AuthenticationProvider，需要手动密码校验
    if (!userDetails.getPassword().equals(inputPassword)) {
      throw new BadCredentialsException("密码错误");
    }

    return new UsernamePasswordAuthenticationToken(inputName, inputPassword,
        userDetails.getAuthorities());
  }

  private boolean validateVerify(String inputVerify) {
    //获取当前线程绑定的request对象
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
        .getRequestAttributes()).getRequest();
    // 不分区大小写
    // 这个validateCode是在servlet中存入session的名字
    String validateCode = ((String) request.getSession().getAttribute("validateCode"))
        .toLowerCase();
    inputVerify = inputVerify.toLowerCase();

    System.out.println("验证码：" + validateCode + "用户输入：" + inputVerify);

    return validateCode.equals(inputVerify);
  }

  @Override
  public boolean supports(Class<?> authentication) {
    // 这里不要忘记，和UsernamePasswordAuthenticationToken比较
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}
